#pragma once 

#include <string>
#include <memory>

#include "base.h"
#include "IRocksdb.h"

namespace rocksdb {
  class DB;
};

namespace helper {
namespace demo {
 
class OptionsArgs;
class Rocksdb : public IRocksdb<Slice, Slice>{
public:
  static Rocksdb * Open(const std::string & name, const OptionsArgs & optionsArgs);
  static bool destroy(const std::string & name, const Options & options);

public:
  using super = IRocksdb<Slice, Slice>;
  using key_type  = typename super::key_type;
  using value_type = typename super::value_type;
  using visitor = typename super::visitor;
  using iterator = typename super::iterator;

  Rocksdb(const std::string & name, const OptionsArgs & optionsArgs) ;
  ~Rocksdb() override ;
 
  DBImpl * instance() override ;

  const std::string & name() const override;

  Status put(const key_type & key, const value_type & value) override ;
  Status get(const key_type & key, std::string & value) const override;
  Status del(const key_type & key) override;
  bool foreach(const visitor & v, const key_type & start, const key_type & end) const override;
  iterator * range(const key_type & start, const key_type & end) const override;

  Status put(const WriteOptions & write, const key_type & key, const value_type & value) override ;
  Status get(const ReadOptions & read, const key_type & key, std::string & value) const override ;
  Status del(const WriteOptions & write, const key_type & key) override ;
  bool foreach(const ReadOptions & read, const visitor & v, const key_type & start, const key_type & end) const override ;
  iterator * range(const ReadOptions & read, const key_type & start, const key_type & end) const override;


public:
  const OptionsArgs & optionsArgs() const override;
  OptionsArgs & optionsArgs() override;

protected:
  bool _open() override ;
  bool _close() override ;

private:
  const std::string name_;
  std::unique_ptr<OptionsArgs> optionsArgs_;
  ::rocksdb::DB * impl_;
};
}//namespace demo
}//namespace helper
